<template>
  <view class="recorder"> </view>
</template>

<script>
export default {
  data() {
    return {
      isUserMedia: false,
      stream: null,
      audio: null,
      recorder: null,
      chunks: []
    }
  },
  mounted() {
    /**
     * 	error 事件的返回状态
     * 	100: 请在HTTPS环境中使用
     * 	101: 浏览器不支持
     *  201: 用户拒绝授权
     *  500: 未知错误
     * */
    if (origin.indexOf('https') === -1) {
      this.$emit('error', '100')
      throw '请在 https 环境中使用本插件。'
    }
    if (!navigator.mediaDevices || !window.MediaRecorder) {
      this.$emit('error', '101')
      throw '当前浏览器不支持'
    }
    this.getRecorderManager()
  },
  destroyed() {
    this.stop()
  },
  methods: {
    getRecorderManager() {
      this.audio = document.createElement('audio')
      navigator.mediaDevices
        .getUserMedia({ audio: true })
        .then((stream) => {
          this.isUserMedia = true
          stream.getTracks().forEach((track) => {
            track.stop()
          })
        })
        .catch((err) => {
          this.onErrorHandler(err)
        })
    },
    start() {
      if (!this.isUserMedia) {
        this.$emit('error', '201')
        return
      }

      navigator.mediaDevices
        .getUserMedia({ audio: true })
        .then((stream) => {
          this.stream = stream
          this.recorder = new MediaRecorder(stream)
          this.recorder.ondataavailable = this.getRecordingData
          this.recorder.onstop = this.saveRecordingData
          this.recorder.start()
        })
        .catch((err) => {
          this.onErrorHandler(err)
        })
    },
    stop() {
      if (!this.recorder) return

      this.recorder.stop()
      this.stream.getTracks().forEach((track) => {
        track.stop()
      })
    },
    getRecordingData(e) {
      this.chunks.push(e.data)
    },
    saveRecordingData() {
      const blob = new Blob(this.chunks, { type: 'audio/mpeg' }),
        localUrl = URL.createObjectURL(blob)

      this.chunks = []
      let lock = true
      const temporaryAudio = document.createElement('audio')
      temporaryAudio.src = localUrl
      temporaryAudio.muted = true
      temporaryAudio.load()
      temporaryAudio.play()
      temporaryAudio.addEventListener('timeupdate', (e) => {
        if (!Number.isFinite(temporaryAudio.duration)) {
          temporaryAudio.currentTime = Number.MAX_SAFE_INTEGER
          temporaryAudio.currentTime = 0
        } else {
          document.body.append(temporaryAudio)
          document.body.removeChild(temporaryAudio)
          if (lock) {
            lock = false
            const recorder = {
              data: blob,
              duration: temporaryAudio.duration,
              localUrl: localUrl
            }
            this.$emit('success', recorder)
          }
        }
      })
    },
    onErrorHandler(err) {
      console.log(err)
      if (err.name === 'NotAllowedError') {
        this.$emit('error', '201')
        throw '用户拒绝了当前的浏览器实例的访问请求'
      }

      if (err.name === 'NotReadableError') {
        this.$emit('error', '101')
        throw '当前浏览器不支持'
      }

      this.$emit('error', '500')
      throw '调用失败，原因不详'
    }
  }
}
</script>
<style></style>
